#include "thread.h"
#include "taask.h"
#include "sigmask.h"
#include "CriticalCtrl.h"

static pthread_once_t once = PTHREAD_ONCE_INIT;


static void suspend_self(event *even)
{
    pthread_mutex_lock(&even->mutex);
    while(even->event_triggered == false)
    {
        pthread_cond_wait(&even->cond, &even->mutex);
    }
    pthread_mutex_unlock(&even->mutex);
}

static void * thread_holdon(void *param)
{
	if (NULL == param)
	{
		return NULL;
	}
    thread_data *thread = (thread_data *)param;
	printf("[%s] entry, ID:%x\n", __func__, thread->pthread);

    //create OK,wait schedule
    suspend_self(thread->even);
    thread->Stat = RUNNING;

	printf("ID: %x get schedule\n ", thread->pthread);

    //once schedule ,call by schedule,open all signal
    #if 1
    //Critcal_Counter = 0;
    pthread_sigmask(SIG_UNBLOCK, &all_sig_set, NULL);
    #endif

    //thread run
    thread->func(thread->param);

    return param;
}


int task_thread_init(TCB * p_tcb, thread_func task_func)
{
    pthread_once(&once, mask_signal_init);

    thread_data *thread;
    pthread_attr_t attr;

    //alloc thread data 
    thread = (thread_data *)(p_tcb->stackTop + 1) - 1;
    p_tcb->stackTop = (match_sizetype *)thread - 1;
    match_sizetype stack_size = (p_tcb->stackTop + 1 - p_tcb->stackEnd) * sizeof(match_sizetype);

    thread->func = task_func;
    thread->even = (event *)malloc(sizeof(event));

    pthread_mutex_init(&thread->even->mutex, NULL);
    pthread_cond_init(&thread->even->cond, NULL);
    thread->even->event_triggered = false;

    pthread_attr_init(&attr);
    pthread_attr_setstack(&attr, (void *)(p_tcb ->task_stack), stack_size);

    entry_Critical_Lock();

    if (pthread_create(&thread ->pthread, &attr, thread_holdon, thread))
	{
		printf ("[%s] create task %s err\n", __func__, p_tcb->taskname);
	}
	else
	{
		printf ("[%s] create task %s success, ID : %x\n", __func__, p_tcb->taskname, (unsigned int)thread->pthread);
		p_tcb->taskID = (unsigned int)thread->pthread;
        thread->Stat = READY2GO;
        pthread_detach(thread->pthread);
	}

    exit_Critical_unlock();

    return 0;
}
